home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Modules / BackSpaceModules / Source / Neko / NekoView.m < prev    next >
Text File  |  1992-06-11  |  10KB  |  476 lines

  1.  
  2. #import "NekoView.h"
  3. #import "Thinker.h"
  4.  
  5. // based on xneko by Masayuki Koba
  6. // hacked into NeXTstep by Eric P. Scott
  7. // severely munged into BackSpace by sam streeper
  8. // go back to the X sources if you port this to other platforms...
  9.  
  10. #import <libc.h>
  11. #import <math.h>
  12. #import <defaults/defaults.h>
  13. #import <appkit/graphics.h>
  14. #import <appkit/Application.h>
  15. #import <appkit/Window.h>
  16. #import <appkit/NXImage.h>
  17. #import <dpsclient/wraps.h>
  18.  
  19. const NXCoord Even[]={
  20.     Mati2,    // STATE_STOP
  21.     Jare2,    // STATE_JARE
  22.     Kaki1,    // STATE_KAKI
  23.     Mati3,    // STATE_AKUBI
  24.     Sleep1,    // STATE_SLEEP
  25.     Awake,    // STATE_AWAKE
  26.     Up1,    // STATE_U_MOVE
  27.     Down1,    // STATE_D_MOVE
  28.     Left1,    // STATE_L_MOVE
  29.     Right1,    // STATE_R_MOVE
  30.     UpLeft1,    // STATE_UL_MOVE
  31.     UpRight1,    // STATE_UR_MOVE
  32.     DownLeft1,    // STATE_DL_MOVE
  33.     DownRight1,    // STATE_DR_MOVE
  34.     UpTogi1,    // STATE_U_TOGI
  35.     DownTogi1,    // STATE_D_TOGI
  36.     LeftTogi1,    // STATE_L_TOGI
  37.     RightTogi1    // STATE_R_TOGI
  38. };
  39.  
  40. const NXCoord Odd[]={
  41.     Mati2,    // STATE_STOP
  42.     Mati2,    // STATE_JARE
  43.     Kaki2,    // STATE_KAKI
  44.     Mati3,    // STATE_AKUBI
  45.     Sleep2,    // STATE_SLEEP
  46.     Awake,    // STATE_AWAKE
  47.     Up2,    // STATE_U_MOVE
  48.     Down2,    // STATE_D_MOVE
  49.     Left2,    // STATE_L_MOVE
  50.     Right2,    // STATE_R_MOVE
  51.     UpLeft2,    // STATE_UL_MOVE
  52.     UpRight2,    // STATE_UR_MOVE
  53.     DownLeft2,    // STATE_DL_MOVE
  54.     DownRight2,    // STATE_DR_MOVE
  55.     UpTogi2,    // STATE_U_TOGI
  56.     DownTogi2,    // STATE_D_TOGI
  57.     LeftTogi2,    // STATE_L_TOGI
  58.     RightTogi2    // STATE_R_TOGI
  59. };
  60.  
  61. #define    PI_PER8            ((double)M_PI/(double)8)
  62. double    SinPiPer8Times3;
  63. double    SinPiPer8;
  64.  
  65. @implementation NekoView
  66.  
  67. - TickCount
  68. {
  69.     if ( ++NekoTickCount >= MAX_TICK )
  70.         NekoTickCount = 0;
  71.  
  72.     if ( NekoTickCount % 2 == 0 )
  73.         if ( NekoStateCount < MAX_TICK )
  74.             NekoStateCount++;
  75.  
  76.     return self;
  77. }
  78.  
  79. - SetNekoState: (int) SetValue
  80. {
  81.     NekoTickCount=0;
  82.     NekoStateCount=0;
  83.  
  84.     NekoState=SetValue;
  85.     return self;
  86. }
  87.  
  88. - DrawNeko: (NXCoord) DrawIcon
  89.     NekoLastIcon.origin.x=DrawIcon;
  90.  
  91.     if (NX_X(&NekoPos) != NekoLastXY.x || NX_Y(&NekoPos)!=NekoLastXY.y)
  92.     {
  93.         static const NXRect zero={ { Space, 0.0 },
  94.             { (NXCoord)BITMAP_WIDTH, (NXCoord)BITMAP_HEIGHT } };
  95.  
  96.         [bitmaps composite:NX_SOVER fromRect:&zero toPoint:&NekoLastXY];        
  97.     }
  98.  
  99.     [bitmaps composite:NX_SOVER fromRect:&NekoLastIcon
  100.         toPoint:&NekoPos.origin];
  101.  
  102.     NekoLastXY=NekoPos.origin;
  103.     return self;
  104. }
  105.  
  106. - NekoDirection
  107. {
  108.     int            NewState;
  109.     double        LargeX, LargeY;
  110.     double        Length;
  111.     double        SinTheta;
  112.  
  113.     if ( NekoMoveDx == 0 && NekoMoveDy == 0 )
  114.         NewState = STATE_STOP;
  115.     else
  116.     {
  117.     LargeX = (double)NekoMoveDx;
  118.     LargeY = (double)(-NekoMoveDy);
  119.     Length = sqrt( LargeX * LargeX + LargeY * LargeY );
  120.     SinTheta = LargeY / Length;
  121.  
  122.     if ( NekoMoveDx > 0 )
  123.     {
  124.         if ( SinTheta > SinPiPer8Times3 )
  125.             NewState = STATE_U_MOVE;
  126.         else if ((SinTheta <= SinPiPer8Times3) && (SinTheta > SinPiPer8))
  127.             NewState = STATE_UR_MOVE;
  128.         else if ((SinTheta <= SinPiPer8) && (SinTheta > -(SinPiPer8)))
  129.             NewState = STATE_R_MOVE;
  130.         else if ((SinTheta <= -SinPiPer8) && (SinTheta > -SinPiPer8Times3))
  131.             NewState = STATE_DR_MOVE;
  132.         else
  133.             NewState = STATE_D_MOVE;
  134.     }
  135.     else
  136.     {
  137.         if ( SinTheta > SinPiPer8Times3)
  138.             NewState = STATE_U_MOVE;
  139.         else if ((SinTheta <= SinPiPer8Times3) && (SinTheta > SinPiPer8))
  140.             NewState = STATE_UL_MOVE;
  141.         else if ((SinTheta <= SinPiPer8 ) && (SinTheta > -SinPiPer8))
  142.             NewState = STATE_L_MOVE;
  143.         else if ((SinTheta <= -SinPiPer8) && (SinTheta > -SinPiPer8Times3))
  144.             NewState = STATE_DL_MOVE;
  145.         else
  146.             NewState = STATE_D_MOVE;
  147.     }
  148.     }
  149.  
  150.     if ( NekoState != NewState )
  151.         [self SetNekoState: NewState];
  152.  
  153.     return self;
  154. }
  155.  
  156. - (BOOL) IsNekoDontMove
  157. {
  158.     if ( NX_X(&NekoPos) == NekoLastXY.x && NX_Y(&NekoPos) == NekoLastXY.y )
  159.         return( YES );
  160.  
  161.     return( NO );
  162. }
  163.  
  164. - (BOOL) IsNekoMoveStart
  165. {
  166.     if ( ( PrevMouseX >= MouseX - IDLE_SPACE
  167.             && PrevMouseX <= MouseX + IDLE_SPACE ) &&
  168.             ( PrevMouseY >= MouseY - IDLE_SPACE 
  169.             && PrevMouseY <= MouseY + IDLE_SPACE ) )
  170.         return( NO );
  171.  
  172.     return( YES );
  173. }
  174.  
  175. - CalcDxDy
  176. {
  177.     double    LargeX, LargeY;
  178.     double    DoubleLength, Length;
  179.  
  180.     if (randCount1 == -100)        // a signal to let values be...
  181.         randCount1 = 200;
  182.     else
  183.     {
  184.           PrevMouseX = MouseX;
  185.         PrevMouseY = MouseY;
  186.     }
  187.  
  188.     if (--randCount1 < 0)
  189.     {
  190.         randCount1 = (random() % (300));
  191.         MouseX = randBetween(-90,bounds.size.width+90);
  192.         MouseY = randBetween(-90,bounds.size.height+90);
  193.     }
  194.  
  195.     LargeX = (double)( MouseX - NX_X(&NekoPos) - BITMAP_WIDTH/2 );
  196.     LargeY = (double)( MouseY - NX_Y(&NekoPos));
  197.  
  198.     DoubleLength = LargeX * LargeX + LargeY * LargeY;
  199.  
  200.     if ( DoubleLength != (double)0 )
  201.     {
  202.         Length = sqrt( DoubleLength );
  203.         if ( Length <= NekoSpeed ) {
  204.             NekoMoveDx = (int)LargeX;
  205.             NekoMoveDy = (int)LargeY;
  206.         } else {
  207.             NekoMoveDx = (int)( ( NekoSpeed * LargeX ) / Length );
  208.             NekoMoveDy = (int)( ( NekoSpeed * LargeY ) / Length );
  209.         }
  210.     }
  211.     else NekoMoveDx = NekoMoveDy = 0;
  212.  
  213.     return self;
  214. }
  215.  
  216.  
  217. - oneStep
  218. {
  219.     usleep(1000000 / 8);    // run at about 8 frames/sec
  220.  
  221.     [self CalcDxDy];
  222.  
  223.     if ( NekoState != STATE_SLEEP )
  224.         [self DrawNeko: NekoTickCount % 2 == 0 ?
  225.             Even[NekoState] : Odd[NekoState]];
  226.     else [self DrawNeko: NekoTickCount % 8 <= 3 ?
  227.             Even[NekoState] :Odd[NekoState]];
  228.  
  229.     [self TickCount];
  230.  
  231.     switch ( NekoState ) 
  232.     {
  233.     case STATE_STOP:
  234.         if ( [self IsNekoMoveStart])
  235.         {
  236.             [self SetNekoState: STATE_AWAKE ];
  237.             break;
  238.         }
  239.         if ( NekoStateCount < TIME_STOP )
  240.             break;
  241.  
  242.         if ( NekoMoveDx < 0 && NX_X(&NekoPos) <= 0 )
  243.             [self SetNekoState: STATE_L_TOGI ];
  244.  
  245.         else if ( NekoMoveDx > 0 &&
  246.                 NX_X(&NekoPos) >= NX_WIDTH(&bounds) - BITMAP_WIDTH )
  247.             [self SetNekoState: STATE_R_TOGI ];
  248.  
  249.         else if ( NekoMoveDy < 0 && NX_Y(&NekoPos) <= 0 )
  250.             [self SetNekoState: STATE_U_TOGI ];
  251.  
  252.         else if ( NekoMoveDy > 0 && NX_Y(&NekoPos) >=
  253.                 NX_HEIGHT(&bounds) - BITMAP_HEIGHT )
  254.             [self SetNekoState: STATE_D_TOGI ];
  255.  
  256.         else [self SetNekoState: STATE_JARE ];
  257.  
  258.         break;
  259.  
  260.     case STATE_JARE:
  261.         if ( [self IsNekoMoveStart] )
  262.         {
  263.             [self SetNekoState: STATE_AWAKE ];
  264.             break;
  265.         }
  266.         if ( NekoStateCount < TIME_JARE )
  267.             break;
  268.  
  269.         [self SetNekoState: STATE_KAKI ];
  270.         break;
  271.  
  272.     case STATE_KAKI:
  273.         if ( [self IsNekoMoveStart])
  274.         {
  275.             [self SetNekoState: STATE_AWAKE ];
  276.             break;
  277.         }
  278.         if ( NekoStateCount < TIME_KAKI )
  279.             break;
  280.  
  281.         [self SetNekoState: STATE_AKUBI ];
  282.         break;
  283.  
  284.     case STATE_AKUBI:
  285.         if ( [self IsNekoMoveStart] )
  286.         {
  287.             [self SetNekoState: STATE_AWAKE ];
  288.             break;
  289.         }
  290.         if ( NekoStateCount < TIME_AKUBI )
  291.             break;
  292.  
  293.         [self SetNekoState: STATE_SLEEP ];
  294.         break;
  295.  
  296.     case STATE_SLEEP:
  297.         if ( [self IsNekoMoveStart] )
  298.         {
  299.             [self SetNekoState: STATE_AWAKE ];
  300.             break;
  301.         }
  302.         break;
  303.  
  304.     case STATE_AWAKE:
  305.         if ( NekoStateCount < TIME_AWAKE )
  306.             break;
  307.  
  308.         [self NekoDirection];
  309.         break;
  310.  
  311.     case STATE_U_MOVE:
  312.     case STATE_D_MOVE:
  313.     case STATE_L_MOVE:
  314.     case STATE_R_MOVE:
  315.     case STATE_UL_MOVE:
  316.     case STATE_UR_MOVE:
  317.     case STATE_DL_MOVE:
  318.     case STATE_DR_MOVE:
  319.         NekoPos.origin.x += NekoMoveDx;
  320.         NekoPos.origin.y += NekoMoveDy;
  321.         [self NekoDirection];
  322.         [self NekoAdjust];
  323.  
  324.         if ( [self IsNekoDontMove])
  325.             [self SetNekoState: STATE_STOP ];
  326.  
  327.         break;
  328.  
  329.     case STATE_U_TOGI:
  330.     case STATE_D_TOGI:
  331.     case STATE_L_TOGI:
  332.     case STATE_R_TOGI:
  333.         if ( [self IsNekoMoveStart] )
  334.         {
  335.             [self SetNekoState: STATE_AWAKE ];
  336.             break;
  337.         }
  338.         if ( NekoStateCount < TIME_TOGI )
  339.             break;
  340.  
  341.         [self SetNekoState: STATE_KAKI ];
  342.         break;
  343.  
  344.     default:
  345.         /* Internal Error */
  346.         [self SetNekoState: STATE_STOP ];
  347.         break;
  348.     }
  349.  
  350.     return self;
  351. }
  352.  
  353. - NekoAdjust
  354. {
  355.     if ( NX_X(&NekoPos) < 0 )
  356.         NekoPos.origin.x = 0;
  357.     else if ( NX_X(&NekoPos) > NX_WIDTH(&bounds) - BITMAP_WIDTH )
  358.         NekoPos.origin.x = NX_WIDTH(&bounds) - BITMAP_WIDTH;
  359.  
  360.     if ( NX_Y(&NekoPos) < 0 )
  361.         NekoPos.origin.y = 0;
  362.     else if ( NX_Y(&NekoPos) > NX_HEIGHT(&bounds) - BITMAP_HEIGHT )
  363.         NekoPos.origin.y = NX_HEIGHT(&bounds) - BITMAP_HEIGHT;
  364.  
  365.     return self;
  366. }
  367.  
  368. - setBitmaps:anObject
  369. {
  370.     bitmaps = anObject;
  371.     return self;
  372. }
  373.  
  374. - bitmaps
  375. {
  376.     return bitmaps;
  377. }
  378.  
  379. - initFrame:(const NXRect *)frameRect
  380. {
  381.     SinPiPer8Times3=sin(PI_PER8*(double)3);
  382.     SinPiPer8=sin(PI_PER8);
  383.  
  384.     [super initFrame:frameRect];
  385.     [self setClipping:NO];
  386.     [self allocateGState];
  387.  
  388.     NXSetRect(&NekoPos,
  389.         (NX_WIDTH(frameRect)-(NXCoord)(BITMAP_WIDTH/2))/2.0,
  390.         (NX_HEIGHT(frameRect)-(NXCoord)(BITMAP_HEIGHT/2))/2.0,
  391.         (NXCoord)BITMAP_WIDTH, (NXCoord)BITMAP_HEIGHT);
  392.     NekoLastXY=NekoPos.origin;
  393.  
  394.     bitmaps=[self findImageNamed:"browncat"];
  395.  
  396.     NXSetRect(&NekoLastIcon, Even[STATE_STOP], 0.0,
  397.         (NXCoord)BITMAP_WIDTH, (NXCoord)BITMAP_HEIGHT);
  398.     NekoSpeed=14;
  399.     [self SetNekoState: STATE_STOP];
  400.     randCount1 = 100;
  401.     return self;
  402. }
  403.  
  404. - drawSelf:(const NXRect *)rects :(int)rectCount
  405. {
  406.     if (!rects || !rectCount) return self;
  407.     PSsetgray(0);
  408.     NXRectFill(rects);
  409.  
  410.     [bitmaps composite:NX_SOVER fromRect:&NekoLastIcon
  411.         toPoint:&NekoPos.origin];
  412.  
  413.     return self;
  414. }
  415.  
  416. - sizeTo:(NXCoord)width :(NXCoord)height
  417. {
  418.     [super sizeTo:width:height];
  419.     [self NekoAdjust];
  420.     return self;
  421. }
  422.  
  423. - (const char *) windowTitle
  424. {    return "Neko";
  425. }
  426.  
  427. - inspector:sender
  428. {
  429.     char buf[MAXPATHLEN];
  430.     
  431.     if (!inspectorPanel)
  432.     {
  433.         sprintf(buf,"%s/Neko.nib",[sender moduleDirectory:"Neko"]);
  434.         [NXApp loadNibFile:buf owner:self withNames:NO];
  435.     }
  436.     return inspectorPanel;
  437. }
  438.  
  439. - (BOOL) useBufferedWindow
  440. {    return YES;
  441. }
  442.  
  443. - findImageNamed:(const char *)name
  444. {
  445.     char buf[1024];
  446.     id ret = [NXImage findImageNamed:name];
  447.     if (ret) return ret;
  448.  
  449.     sprintf(buf,"%s/%s.tiff",[(BSThinker()) moduleDirectory:"Neko"],name);
  450.     ret = [[NXImage alloc] initFromFile:buf];
  451.     [ret setName:name];
  452.     return ret;
  453. }
  454.  
  455. - inspectorWillBeRemoved
  456. {
  457.     [infoWindow orderOut:self];
  458.     return self;
  459. }
  460.  
  461. - mouseDown:(NXEvent *)event
  462. {
  463.     NXPoint loc = event->location;
  464.     [self convertPoint:&loc fromView:nil];
  465.     randCount1 = -100;
  466.       PrevMouseX = MouseX;
  467.     PrevMouseY = MouseY;
  468.     MouseX = loc.x;
  469.     MouseY = loc.y;
  470.     return self;
  471. }
  472.  
  473.  
  474. @end
  475.